﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIIV.Data;
using SIIV.Business.Exceptions;

namespace SIIV.Business
{
    public class AnimalBusiness: Animal
    {
        public List<Animal> ObtenerAnimales(int? idVeterinario, string nombre, decimal? pesoInicial, decimal? pesoFinal, char? sexo, short? idTipoAnimal)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                decimal dPesoInicial = pesoInicial.HasValue ? pesoInicial.Value : default(decimal);
                decimal dPesoFinal = pesoFinal.HasValue ? pesoFinal.Value : default(decimal);
                string sSexo = sexo.HasValue ? sexo.Value.ToString() : default(string);
                short sTipoAnimal = idTipoAnimal.HasValue ? idTipoAnimal.Value : default(short);

                return model.Animales
                    .Include("TipoDeAnimal")
                    .Include("EstadoDeAnimal")
                    .Include("Veterinario")
                    .Include("Campo")
                    .Include("AnimalPadre")
                    .Where(a =>
                        !a.IdEstadoAnimal.Equals(3) &&
                        (idVeterinario.HasValue ? a.IdVeterinario.Equals(idVeterinario.Value) : true) &&
                        (nombre.Equals(string.Empty) ? true : a.Nombre.Contains(nombre)) &&
                        (dPesoInicial.Equals(default(decimal)) ? true : a.Peso >= dPesoInicial) &&
                        (dPesoFinal.Equals(default(decimal)) ? true : a.Peso <= dPesoFinal) &&
                        (sSexo.Equals(default(string)) ? true : a.Sexo.Equals(sSexo)) &&
                        (sTipoAnimal.Equals(default(short)) ? true : a.IdTipoAnimal.Equals(sTipoAnimal))).ToList();
            }
        }

        public List<Animal> ObtenerAnimalesSinSerElMismo(int? idVeterinario, string nombre, decimal? pesoInicial, decimal? pesoFinal, char? sexo, short? idTipoAnimal)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                decimal dPesoInicial = pesoInicial.HasValue ? pesoInicial.Value : default(decimal);
                decimal dPesoFinal = pesoFinal.HasValue ? pesoFinal.Value : default(decimal);
                string sSexo = sexo.HasValue ? sexo.Value.ToString() : default(string);
                short sTipoAnimal = idTipoAnimal.HasValue ? idTipoAnimal.Value : default(short);

                return model.Animales
                    .Include("TipoDeAnimal")
                    .Include("EstadoDeAnimal")
                    .Include("Veterinario")
                    .Include("Campo")
                    .Include("AnimalPadre")
                    .Where(a =>
                        a.IdEstadoAnimal.Equals(1) &&
                        (idVeterinario.HasValue ? a.IdVeterinario.Equals(idVeterinario.Value) : true) &&
                        (nombre.Equals(string.Empty) ? true : a.Nombre != nombre) &&
                        (dPesoInicial.Equals(default(decimal)) ? true : a.Peso >= dPesoInicial) &&
                        (dPesoFinal.Equals(default(decimal)) ? true : a.Peso <= dPesoFinal) &&
                        (sSexo.Equals(default(string)) ? true : a.Sexo.Equals(sSexo)) &&
                        (sTipoAnimal.Equals(default(short)) ? true : a.IdTipoAnimal.Equals(sTipoAnimal))).ToList();
            }
        }

        public void EliminarAnimal(int idAnimal)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                Animal animal = model.Animales.Single(a => a.IdAnimal.Equals(idAnimal));
                animal.IdEstadoAnimal = 3;
                model.SaveChanges();
            }
        }

        public void CrearAnimal(string nombre, decimal peso, int? idAnimalPadre, char sexo, short idTipoAnimal, DateTime fechaNacimiento, int idVeterinario)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                if (fechaNacimiento > DateTime.Now.Date)
                {
                    throw new FunctionalException("La fecha de nacimiento no puede ser superior a hoy.");
                }
                if (model.Animales.Any(a => a.Nombre.Equals(nombre) && a.IdVeterinario.Equals(idVeterinario)))
                {
                    throw new FunctionalException("Ya existe un animal con el nombre ingresado.");
                }
                model.AddToAnimales(new Animal()
                {
                    FechaNacimiento = fechaNacimiento,
                    IdAnimalPadre = idAnimalPadre,
                    IdEstadoAnimal = 1,
                    IdTipoAnimal = idTipoAnimal,
                    IdVeterinario = idVeterinario,
                    Nombre = nombre,
                    Peso = peso,
                    Sexo = sexo.ToString()
                });
                model.SaveChanges();
            }
        }

        public void ActualizarAnimal(int idAnimal, string nombre, decimal peso, int? idAnimalPadre, char sexo, short idTipoAnimal, DateTime fechaNacimiento)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                if (fechaNacimiento > DateTime.Now.Date)
                {
                    throw new FunctionalException("La fecha de nacimiento no puede ser superior a hoy.");
                }
                Animal animal = model.Animales.Single(a => a.IdAnimal.Equals(idAnimal));
                if (!animal.Nombre.Equals(nombre) && model.Animales.Any(a => a.Nombre.Equals(nombre) && a.IdVeterinario.Equals(animal.IdVeterinario) && a.IdCampo == animal.IdCampo))
                {
                    throw new FunctionalException("Ya existe un animal con el nombre ingresado.");
                }
                if (animal.Nombre == nombre && animal.Peso == peso && animal.IdAnimalPadre == idAnimalPadre && animal.Sexo == sexo.ToString()
                    && animal.IdTipoAnimal == idTipoAnimal && animal.FechaNacimiento == fechaNacimiento)
                {
                    throw new FunctionalException("Debe Modificar algún dato del Animal");
                }
                else
                {
                    animal.Nombre = nombre;
                    animal.Peso = peso;
                    animal.IdAnimalPadre = idAnimalPadre;
                    animal.Sexo = sexo.ToString();
                    animal.IdTipoAnimal = idTipoAnimal;
                    animal.FechaNacimiento = fechaNacimiento;
                    model.SaveChanges();
                }
            }
        }

        public List<TipoDeAnimal> ObtenerTiposDeAnimales()
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.TiposDeAnimales.ToList();
            }
        }

        public List<EstadoDeAnimal> ObtenerEstados()
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.EstadosDeAnimales.ToList();
            }
        }

        public void ActualizarAnimal(int idAnimal, string nombre, decimal peso, int? idAnimalPadre, char sexo, short idTipoAnimal, DateTime fechaNacimiento, short idEstado, int? idCampo)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                if (fechaNacimiento > DateTime.Now.Date)
                {
                    throw new FunctionalException("La fecha de nacimiento no puede ser superior a hoy.");
                }
                Animal animal = model.Animales.Single(a => a.IdAnimal.Equals(idAnimal));
                if (!animal.Nombre.Equals(nombre) && model.Animales.Any(a => a.Nombre.Equals(nombre) && a.IdVeterinario.Equals(animal.IdVeterinario) && a.IdCampo == idCampo))
                {
                    throw new FunctionalException("Ya existe un animal con el nombre ingresado.");
                }
                if ((animal.FechaNacimiento != fechaNacimiento || animal.IdAnimalPadre != idAnimalPadre || animal.IdTipoAnimal != idTipoAnimal || animal.Sexo[0] != sexo) && animal.Muestras.Any(m => m.Analisis.Count > 0))
                {
                    throw new FunctionalException("La fecha de nacimiento, el animal padre o el tipo de animal no pueden modificarse dado que el animal ya tiene análisis en curso.");
                }
                animal.Nombre = nombre;
                animal.Peso = peso;
                animal.IdAnimalPadre = idAnimalPadre;
                animal.Sexo = sexo.ToString();
                animal.IdTipoAnimal = idTipoAnimal;
                animal.FechaNacimiento = fechaNacimiento;
                animal.IdCampo = idCampo;
                animal.IdEstadoAnimal = idEstado;
                model.SaveChanges();
            }
        }

        public Animal VerificarExisteAnimal(string nombreAnimal, int idVeterinario)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                Animal animal = model.Animales.SingleOrDefault(a => a.Nombre.Equals(nombreAnimal) && a.IdVeterinario.Equals(idVeterinario));

                if (animal == null)
                {
                    return animal;
                }
                else
                {
                    throw new FunctionalException(" Animal existente");
                }
            }
        }

        public Animal VerificarModAnimal(int idAnimal, string nombreAnimal, int idVeterinario)
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                Animal animal = model.Animales.SingleOrDefault(a => a.Nombre.Equals(nombreAnimal) && !a.IdAnimal.Equals(idAnimal) && a.IdVeterinario.Equals(idVeterinario));
                if (animal == null)
                {
                    return animal;
                }
                else
                {
                    throw new FunctionalException("    El usuario ya existe");
                }
            }
        }

        public List<Usuario> ObtenerVeterinarios()
        {
            using (SIIVDataModel model = new SIIVDataModel())
            {
                return model.Usuarios.Where(u => u.Animales.Count > 0 && u.Activo).ToList();
            }
        }
    }
}
